/*
 * $Id: $
 */
package org.rcgwt.client.ui.grid.renderer;

import java.util.Iterator;

import org.rcgwt.client.ui.grid.internal.model.IGridModel;
import org.rcgwt.client.ui.grid.internal.model.IHeaderModel;
import org.rcgwt.client.ui.grid.internal.model.ITitleCellModel;
import org.rcgwt.client.ui.grid.internal.model.ITitleRowModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModelElements;
import org.rcgwt.client.ui.grid.provider.IColumnProvider;
import org.rcgwt.client.ui.grid.theme.CssStyle;
import org.rcgwt.client.ui.grid.theme.IGridTheme;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.TableSectionElement;

/**
 * 
 * @author Olivier Oeuillot (latest modification by $Author: $)
 * @version $Revision: $ $Date: $
 */
public class DefaultTitleRowRenderer extends AbstractRenderer<ITitleRowModel>
        implements ITitleRowRenderer {

    private static final String TITLE_ROW_CELL_PROPERTY = "_titleRowCell";

    public Element render(IViewRenderContext viewRenderContext,
            Element parentElement, ITitleRowModel titleRow, int renderedIndex) {

        assert parentElement instanceof TableSectionElement : "Invalid parent type ("
                + parentElement + ")";

        Element rowElement;

        if (titleRow.isFocusable()) {
            Element focusableParent = impl.createFocusable();
            rowElement = focusableParent;

            viewRenderContext.getGridRenderContext().getGridModel()
                    .getGridWidget().getGridModelController()
                    .installElementEventsListener(viewRenderContext, titleRow,
                            focusableParent, null);

            CssStyle titleRowCssStyle = viewRenderContext
                    .getGridRenderContext().getTheme()
                    .getFocusedTitleRowCssStyle(titleRow);
            rowElement.setClassName(titleRowCssStyle.getClassName());

        } else {
            rowElement = parentElement.getOwnerDocument().createDivElement();
        }

        update(viewRenderContext, rowElement, titleRow, renderedIndex);

        return rowElement;
    }

    @Override
    protected CssStyle getCssStyle(IViewRenderContext renderContext,
            ITitleRowModel titleRow) {
        return renderContext.getGridRenderContext().getTheme()
                .getTitleRowCssStyle(titleRow);
    }

    @Override
    public void update(IViewRenderContext viewRenderContext,
            Element rowElement, ITitleRowModel titleRow, int renderedIndex) {
        super.update(viewRenderContext, rowElement, titleRow, renderedIndex);

        viewRenderContext.getViewModel().getViewModelElements()
                .setTitleRowElement(titleRow, rowElement, renderedIndex);
    }

    @SuppressWarnings("boxing")
    @Override
    protected void updateContent(IViewRenderContext viewRenderContext,
            Element titleRowElement, ITitleRowModel titleRowModel) {

        IViewModel viewModel = viewRenderContext.getViewModel();
        IGridModel gridModel = viewModel.getGridModel();
        IGridTheme theme = viewRenderContext.getGridRenderContext().getTheme();

        /*
         * int headerHeight = theme.getHorizontalHeaderHeight(viewModel); if
         * (headerHeight > 0) {
         * rowElement.getStyle().setPropertyPx(Styles.HEIGHT, headerHeight); }
         */

        if (titleRowModel.isFocusable()) {
            // titleRowElement = titleRowElement.getFirstChildElement();
        }

        int cellElementsCount = 0;
        NodeList<Node> children = null;
        if (titleRowElement.hasChildNodes()) {
            children = titleRowElement.getChildNodes();

            cellElementsCount = children.getLength();
        }

        IColumnProvider columnProvider = gridModel.getGridWidget()
                .getColumnProvider();

        Iterator<Integer> columnIterator = columnProvider
                .getColumnModelIndexes(titleRowModel.getModelIndex());

        ITitleCellModel titleCellModels[] = titleRowModel.listTitleCellModels();

        int titleCellIndex = 0;
        int renderedColumnIndex = 0;
        for (; columnIterator.hasNext(); renderedColumnIndex++) {
            int columnModelIndex = columnIterator.next();

            ITitleCellModel titleCell = titleCellModels[columnModelIndex];

            IRenderer<ITitleCellModel> titleCellRenderer = theme
                    .getTitleCellRenderer(titleCell);

            Element titleCellElement = null;
            for (; titleCellIndex < cellElementsCount;) {
                Node node = children.getItem(titleCellIndex++);
                if (node.getNodeType() != Node.ELEMENT_NODE) {
                    continue;
                }

                Element e = Element.as(node);

                if (e.getPropertyBoolean(TITLE_ROW_CELL_PROPERTY)) {
                    titleCellElement = e;
                    break;
                }
            }

            if (titleCellElement != null) {
                titleCellRenderer.update(viewRenderContext, titleCellElement,
                        titleCell, renderedColumnIndex);

                continue;
            }

            titleCellElement = titleCellRenderer.render(viewRenderContext,
                    titleRowElement, titleCell, renderedColumnIndex);

            titleCellElement.setPropertyBoolean(TITLE_ROW_CELL_PROPERTY, true);

            titleRowElement.appendChild(titleCellElement);
        }

    }

    @Override
    public void updateLayout(IViewRenderContext viewRenderContext,
            ITitleRowModel titleRowModel, Element element, int totalSize,
            int[] sizesByColumnModelIndex, int titleRowHeight) {

        IViewModel viewModel = viewRenderContext.getViewModel();
        IViewModelElements viewModelElements = viewModel.getViewModelElements();

        IGridTheme gridTheme = viewRenderContext.getGridRenderContext()
                .getTheme();

        Style style = element.getStyle();

        style.setPropertyPx(Styles.WIDTH, totalSize
                + gridTheme.getMaximumVerticalScrollBarWidth());

        int margins[] = null;

        int titleCellRenderedIndex = 0;
        for (ITitleCellModel titleCellModel : titleRowModel
                .listTitleCellModels()) {

            Element titleCellElement = viewModelElements
                    .getTitleCellElement(titleCellModel);
            if (element == null) {
                continue;
            }

            ITitleCellRenderer titleCellRenderer = gridTheme
                    .getTitleCellRenderer(titleCellModel);

            int colspan = titleCellModel.getColumnModel().getColumn()
                    .getTitleColSpan(titleRowModel.getModelIndex());
            if (colspan < 1) {
                colspan = 1;
            }

            int cellWidth = 0;
            for (int i = 0; i < colspan; i++) {
                cellWidth += sizesByColumnModelIndex[titleCellModel
                        .getModelIndex()];
            }

            if (titleCellRenderedIndex == 0) {
                if (margins == null) {
                    margins = gridTheme.getTableMargins();
                }
                cellWidth += margins[3];

            } else if (titleCellRenderedIndex == sizesByColumnModelIndex.length - 1) {
                if (margins == null) {
                    margins = gridTheme.getTableMargins();
                }
                cellWidth += margins[1];
            }

            titleCellRenderer.updateLayout(viewRenderContext, titleCellModel,
                    titleCellElement, cellWidth, titleRowHeight);

            titleCellRenderedIndex++;
        }
    }

    @Override
    public int getSize(IViewRenderContext viewRenderContext,
            ITitleRowModel titleRowModel, Element titleRowElement) {

        IGridTheme gridTheme = viewRenderContext.getGridRenderContext()
                .getTheme();

        IHeaderModel headerModel = titleRowModel.getHeader();

        if (headerModel.getOrientation() == IHeaderModel.Orientation.HORIZONTAL) {

            return gridTheme.getHorizontalHeaderHeight(headerModel);
        }

        return gridTheme.getVerticalHeaderWidth(headerModel);
    }

    @Override
    public void setFocus(IViewRenderContext viewRenderContext,
            ITitleRowModel titleRowModel, Element titleRowElement) {
        impl.focus((com.google.gwt.user.client.Element) titleRowElement);
    }
}
